home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 1258 / samples / track.jav < prev   
Text File  |  1996-03-09  |  11KB  |  492 lines

  1. // Track.java
  2.  
  3. /*
  4.  * Copyright (c) 1996 by Corey Trager.
  5.  *
  6.  * Permission to use, copy, and distribute this software for
  7.  * any purpose and without fee is hereby granted provided
  8.  * that this copyright notice appears in all copies.
  9.  *
  10.  */
  11.  
  12. // Track is the abstract class
  13. // StraightTrack, CurvedTrack, and SwitchTrack are
  14. // all derived from Track.
  15.  
  16. // The Track class and the TrackCollection class
  17. // collaborate
  18.  
  19.  
  20. import java.lang.Math;
  21. // import java.awt.*;
  22. import java.awt.Graphics;
  23. import java.awt.Color;
  24.  
  25. abstract class Track {
  26.  
  27.     // Increment each time a track is constructed
  28.     private protected static int nextId = 0;
  29.     
  30.     // We need to talk to our container sometimes
  31.     static TrackCollection tc;
  32.  
  33.     // Constants
  34.     static final int EMPTY = 999;
  35.     static final double SNAP_DIST = 6.0;
  36.     static final int NOT_GRIPPED = 0;
  37.     static final int TRANSLATE_MODE = 1;
  38.     static final int ROTATE_MODE_XY = 2;
  39.     static final int ROTATE_MODE_PQ = 3;
  40.     static final int GRIP_RANGE = 9;
  41.     static final int TIE_SIZE = 3;
  42.  
  43.     int id; // id happens to == index in lines array
  44.  
  45.     // state
  46.     int transformMode = NOT_GRIPPED;
  47.     boolean isGripped = false;
  48.  
  49.     // Ties
  50.     Line ties[];
  51.     int tieCnt;
  52.     int connections[];
  53.     DblPoint connectionPoints[];
  54.     int connectionCnt;
  55.  
  56.     private protected double x, y, ox, oy;
  57.     double cx, cy;
  58.  
  59.     abstract void move(int argX, int argY);
  60.     abstract void rotate(double theta);
  61.     
  62.     Track () {
  63.         id = nextId++;
  64.     }
  65.     
  66.     void draw (Graphics g) {
  67.         
  68.         int i;
  69.     
  70.         for (i = 0; i < tieCnt; i++)
  71.             ties[i].draw(g);    
  72.         
  73.         for (i = 0; i < connectionCnt; i++) {
  74.             if (connections[i] != EMPTY)
  75.                 g.setColor (Color.green);
  76.             else
  77.                 g.setColor (Color.red);
  78.             g.drawOval (
  79.                 (int)connectionPoints[i].x - 3,
  80.                 (int)connectionPoints[i].y - 3,
  81.                 6, 6); 
  82.         }
  83.     }
  84.  
  85.     boolean isConnectedTo (int id) {
  86.  
  87.         for (int i = 0; i < connectionCnt; i++) {
  88.             if (connections[i] == id)
  89.                 return true;
  90.         }
  91.         
  92.         return false;
  93.     }
  94.     
  95.     // Get track connected to this track which is
  96.     // NOT the same as the incoming track
  97.     int getNext (int id) {
  98.         for (int i = 0; i < connectionCnt; i++) {
  99.             if (connections[i] != EMPTY
  100.             && connections[i] != id)
  101.                 return connections[i];
  102.         }
  103.         
  104.         return -1;
  105.     }
  106.     
  107.     void instantiateObjects() {
  108.         ties = new Line[tieCnt];
  109.         connections = new int[connectionCnt];
  110.         connectionPoints = new DblPoint[connectionCnt];
  111.         
  112.         for (int i = 0; i < tieCnt; i++)
  113.             ties[i] = new Line(new DblPoint(0,0),new DblPoint(0,0));
  114.  
  115.         for (int i = 0; i < connectionCnt; i++) {
  116.             connections[i] = EMPTY;
  117.             connectionPoints[i] = new DblPoint (0, 0);
  118.         }
  119.     }
  120.     
  121.  
  122.     abstract void setMainLines();
  123.     abstract void setTies();
  124.     abstract void setConnectionPoints();
  125.  
  126.     void restore () {
  127.  
  128.         for (int i = 0; i < connectionCnt; i++)
  129.             connections[i] = Track.EMPTY;
  130.             
  131.     }
  132.     
  133.     int appendRunPoints (DblPoint pts[], int index, int id) {
  134.         if (connections[0] == id) {
  135.             for (int i = 0; i < tieCnt; i++) {
  136.                 pts[index] = new DblPoint (ties[i].c);
  137.                 index++;
  138.             }
  139.             pts[index] = new DblPoint (connectionPoints[1]);
  140.             index++;
  141.         }
  142.         else {
  143.             for (int i = tieCnt - 1; i > -1; i--) {
  144.                 pts[index] = new DblPoint (
  145.                     ties[i].c.x,
  146.                     ties[i].c.y);
  147.                 index++;
  148.             }
  149.             pts[index] = new DblPoint (connectionPoints[0]);
  150.             index++;
  151.         }
  152.         return index;
  153.     }
  154.     
  155.     void rotate(int x, int y) {
  156.  
  157.         DblPoint pivot;
  158.         DblPoint grip;
  159.         DblPoint mouse = new DblPoint ((double) x, ((double) y));
  160.         
  161.         if (transformMode == ROTATE_MODE_XY) {
  162.             pivot = new DblPoint (connectionPoints[0]);
  163.             grip = new DblPoint (connectionPoints[1]);
  164.         }
  165.         else {
  166.             pivot = new DblPoint (connectionPoints[1]);
  167.             grip = new DblPoint (connectionPoints[0]);
  168.         }
  169.         
  170.         // The y grows larger when moving down but I can't
  171.         // think that way.  Make y increase as I move the
  172.         // mouse up
  173.                     
  174.         double thetaMouse = - (pivot.angleToPoint (mouse));            
  175.         double thetaGrip = - (pivot.angleToPoint (grip));
  176.  
  177.         if (thetaMouse >= thetaGrip) {
  178.             double thetaCCW = thetaMouse - thetaGrip; // counter-clockwise
  179.             if (thetaCCW <= Geometry.ONE_EIGHTY_DEGREES)
  180.                 rotate (thetaCCW);
  181.             else
  182.                 rotate (-1.0 * (Geometry.THREE_SIXTY_DEGREES - thetaCCW));
  183.         }
  184.         else {
  185.             double thetaCW = thetaMouse - thetaGrip;
  186.             if (thetaCW < -Geometry.ONE_EIGHTY_DEGREES)
  187.                 rotate (thetaCW);
  188.             else
  189.                 rotate (Geometry.THREE_SIXTY_DEGREES + thetaCW);
  190.         }    
  191.     }
  192.  
  193.  
  194.  
  195.     void releaseGrip () {
  196.         transformMode = NOT_GRIPPED;
  197.     }
  198.  
  199.     void detach () {
  200.  
  201.         for (int i = 0; i < connectionCnt; i++) {
  202.             if (connections[i] != EMPTY) {
  203.                 tc.getTrack(connections[i]).detach(id);
  204.                 connections[i] = EMPTY;
  205.             }
  206.         }
  207.     
  208.     }    
  209.  
  210.     void detach (int otherId) {
  211.     
  212.         // Only detach end which
  213.         // is connected to incoming guy
  214.         for (int i = 0; i < connectionCnt; i++) {
  215.             if (connections[i] == otherId)
  216.                 connections[i] = EMPTY;
  217.         }
  218.         
  219.     }
  220.     
  221.     int tryToGrip (int x, int y, double distArg ) {
  222.         double distC;
  223.         double distXY;
  224.         double distPQ;
  225.         DblPoint xy = connectionPoints[0];
  226.         DblPoint pq = connectionPoints[1];
  227.         distC = Math.sqrt ((this.cx - (double) x) * (this.cx - (double) x)
  228.             + (this.cy - y) * (this.cy - (double) y));
  229.         distXY = Math.sqrt ((xy.x - (double) x) * (xy.x - (double) x)
  230.             + (xy.y - y) * (xy.y - (double) y));
  231.         distPQ = Math.sqrt ((pq.x - (double) x) * (pq.x - (double) x)
  232.             + (pq.y - y) * (pq.y - (double) y));
  233.  
  234.         // check if gripped in the middle
  235.         if (distC < GRIP_RANGE
  236.         || distXY < GRIP_RANGE
  237.         || distPQ < GRIP_RANGE) {    
  238.             if (distC <= distXY && distC <= distPQ) {
  239.                 transformMode = TRANSLATE_MODE;
  240.                 distArg = distC;
  241.             }
  242.             else
  243.             if (distXY <= distC && distXY <= distPQ) {
  244.                 transformMode = ROTATE_MODE_PQ;
  245.                 distArg = distXY;
  246.             }
  247.             else {
  248.                 transformMode = ROTATE_MODE_XY;
  249.                 distArg = distPQ;
  250.             }
  251.         }
  252.         else {
  253.             transformMode = NOT_GRIPPED;
  254.         }
  255.         
  256.         return transformMode;
  257.     }
  258.     
  259.     void prepareForCircuitInquiry () {}                
  260. }
  261. //////////////////////////////////////////////////////
  262. //////////////////////////////////////////////////////
  263. // StraightTrack
  264. //////////////////////////////////////////////////////
  265. //////////////////////////////////////////////////////
  266. class StraightTrack extends Track {
  267.  
  268.     // Main line
  269.     Line ln;
  270.     
  271.     StraightTrack (int x, int y) {
  272.  
  273.         tieCnt = 3;
  274.         connectionCnt = 2;
  275.  
  276.         instantiateObjects();
  277.     
  278.         // save original position
  279.         ox = (double) x;
  280.         oy = (double) y;
  281.  
  282.         restore ();
  283.     }
  284.  
  285.     void setMainLines () {
  286.         ln = new Line(
  287.             new DblPoint(x, y),
  288.             new DblPoint(x + 40.0, y));
  289.     }
  290.     
  291.     void setTies () {
  292.     
  293.         double up = ln.c.y + TIE_SIZE;
  294.         double down = ln.c.y - TIE_SIZE;
  295.         double inc = 10.0;
  296.         ties[0].v1.x = x + inc;
  297.         ties[0].v1.y = up;
  298.         ties[0].v2.x = x + inc; 
  299.         ties[0].v2.y = down;
  300.         ties[1].v1.x = ln.c.x;
  301.         ties[1].v1.y = up;
  302.         ties[1].v2.x = ln.c.x;
  303.         ties[1].v2.y = down;
  304.         ties[2].v1.x = x + (3 * inc);
  305.         ties[2].v1.y = up;
  306.         ties[2].v2.x = x + (3 * inc);
  307.         ties[2].v2.y = down;
  308.     }
  309.  
  310.     void setConnectionPoints () {
  311.         connectionPoints[0].x = ln.v1.x;
  312.         connectionPoints[0].y = ln.v1.y;
  313.         connectionPoints[1].x = ln.v2.x;
  314.         connectionPoints[1].y = ln.v2.y;
  315.         cx = ln.c.x;
  316.         cy = ln.c.y;
  317.     }
  318.     
  319.     void restore() {
  320.         x = ox;
  321.         y = oy;
  322.         super.restore();
  323.         setMainLines();
  324.         setTies();
  325.         setConnectionPoints();
  326.     }
  327.  
  328.     void move(int argX, int argY) {
  329.  
  330.         DblPoint vector = ln.moveTo (
  331.             (double) argX, (double) argY);
  332.  
  333.         for (int i = 0; i < tieCnt; i++)
  334.             ties[i].translate(vector);
  335.  
  336.         setConnectionPoints();
  337.     }
  338.     
  339.     void rotate(double theta) {
  340.         
  341.         DblPoint vector;
  342.  
  343.         if (transformMode == ROTATE_MODE_XY)
  344.             vector = DblPoint.vector (Geometry.ORIGIN, ln.v1);
  345.         else if (transformMode == ROTATE_MODE_PQ)
  346.             vector = DblPoint.vector (Geometry.ORIGIN, ln.v2);
  347.         else
  348.             vector = DblPoint.vector (Geometry.ORIGIN, ln.c);
  349.  
  350.         ln.rotate(vector, theta);
  351.         for (int i = 0; i < tieCnt; i++)
  352.             ties[i].rotate (vector, theta);
  353.         
  354.         setConnectionPoints();
  355.  
  356.     }
  357.  
  358.     void draw (Graphics g) {
  359.  
  360.         if (transformMode == NOT_GRIPPED)
  361.             g.setColor(Color.black);
  362.         else
  363.             g.setColor(Color.blue);
  364.         
  365.         ln.draw (g);
  366.         super.draw(g);        
  367.     }
  368.     
  369.     
  370.     
  371.     
  372. }  // end class StraightTrack
  373.  
  374. ///////////////////////////////////////////////
  375. ///////////////////////////////////////////////
  376. // CurvedTrack
  377. ///////////////////////////////////////////////
  378. ///////////////////////////////////////////////
  379.  
  380. // You must construct a piece of track as the upper
  381. // right quadrant of a circle.  After you construct
  382. // it you can move it whereever you want
  383.  
  384. class CurvedTrack extends Track {
  385.  
  386.     // Main line
  387.     Arc arc;
  388.  
  389.     CurvedTrack (int x, int y)
  390.     {
  391.         tieCnt = 5;
  392.         connectionCnt = 2;
  393.         
  394.         instantiateObjects();
  395.                 
  396.         ox = (double) x;
  397.         oy = (double) y;
  398.  
  399.         restore ();        
  400.     }
  401.  
  402.  
  403.     void setMainLines () {
  404.         arc = new Arc(new DblPoint(x,y+40), 40, 0.0, Geometry.NINETY_DEGREES);
  405.     }
  406.     
  407.     void setTies () {
  408.  
  409.         double centerX = arc.c.x;
  410.         double centerY = arc.c.y;
  411.         
  412.         double theta;
  413.         DblPoint vector = DblPoint.vector (Geometry.ORIGIN, arc.c);
  414.         DblPoint pt = new DblPoint (0,0);
  415.         
  416.         for (int i = 0; i < tieCnt; i++) {
  417.             ties[i].v1.x = centerX;
  418.             ties[i].v1.y = centerY + 3;
  419.             ties[i].v2.x = centerX;
  420.             ties[i].v2.y = centerY - 3;
  421.             theta = Geometry.degreesToRadians (-15.0 * (i + 1));
  422.             ties[i].rotate (vector, theta);
  423.             pt.x = Math.sin (-theta) * arc.radius;
  424.             pt.y = - Math.cos (theta) * arc.radius;
  425.             ties[i].translate (pt);
  426.         }
  427.     
  428.     }
  429.  
  430.     void setConnectionPoints () {
  431.         connectionPoints[0].x = arc.v1.x;
  432.         connectionPoints[0].y = arc.v1.y;
  433.         connectionPoints[1].x = arc.v2.x;
  434.         connectionPoints[1].y = arc.v2.y;
  435.         cx = arc.arcTo.x;
  436.         cy = arc.arcTo.y;
  437.     }
  438.  
  439.     void restore() {
  440.  
  441.         x = ox;
  442.         y = oy;
  443.         super.restore();
  444.         setMainLines();
  445.         setTies();
  446.         setConnectionPoints();
  447.         rotate(Geometry.FORTY_FIVE_DEGREES);
  448.     }
  449.  
  450.     void move(int argX, int argY) {
  451.  
  452.         DblPoint vector = arc.moveTo (
  453.             (double) argX, (double) argY);
  454.  
  455.         for (int i = 0; i < tieCnt; i++)
  456.             ties[i].translate(vector);
  457.  
  458.         setConnectionPoints();
  459.  
  460.     }
  461.  
  462.     void rotate(double theta) {
  463.     
  464.         DblPoint vector;
  465.  
  466.         if (transformMode == ROTATE_MODE_XY)
  467.             vector = DblPoint.vector (Geometry.ORIGIN, arc.v1);
  468.         else if (transformMode == ROTATE_MODE_PQ)
  469.             vector = DblPoint.vector (Geometry.ORIGIN, arc.v2);
  470.         else
  471.             vector = DblPoint.vector (Geometry.ORIGIN, arc.arcTo);
  472.  
  473.         arc.rotate(vector, theta);
  474.         for (int i = 0; i < tieCnt; i++)
  475.             ties[i].rotate(vector, theta);
  476.         
  477.         setConnectionPoints();
  478.     }
  479.  
  480.     void draw (Graphics g) {
  481.  
  482.         if (transformMode == NOT_GRIPPED)
  483.             g.setColor(Color.black);
  484.         else
  485.             g.setColor(Color.blue);
  486.         
  487.         arc.draw (g);
  488.         
  489.         super.draw(g);
  490.     }
  491. }
  492.